package edu.usm.predatorwars;

import java.io.PrintStream;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

import edu.predatorwars.shared.models.Board;
import edu.predatorwars.shared.models.Creature;
import edu.predatorwars.shared.models.Location;
import edu.predatorwars.shared.models.Move;
import edu.predatorwars.shared.models.Player;

public class PlayableImpl implements Playable {
	
	private final Scanner scanner;
	private final PrintStream streamToWrite;

	public PlayableImpl(Scanner scanner, PrintStream streamToWrite) {
		this.scanner = scanner;
		this.streamToWrite = streamToWrite;
	}

	public void onBoardUpdate(Board arg0, List<Player> arg1, int myX, int myY) {
		StringBuffer[] buffers = new StringBuffer[9];
		Location[][] locs = arg0.getLocations();
		for(int i = 0; i < locs.length; i++) {
			for (int j = 0; j< locs[0].length; j++) {
				if (buffers[j] == null) {
					buffers[j] = new StringBuffer();
				}
				if (locs[i][j] == null) {
					buffers[j].append("?\t");
				} else if (i == myX && j == myY) {
					buffers[j].append("U\t");
				} else if (locs[i][j].getPlayer() != null) {
					buffers[j].append("E\t");
				} else if (!locs[i][j].getTerrain().isTraversable()
							|| locs[i][j].getTerrain().isSightBlocked()) {
					buffers[j].append("B\t");
				} else if (locs[i][j].getResource() != null) {
					buffers[j].append("R\t");
				} else {
					buffers[j].append("O\t");
				}
			}
		}
		
		for(int i = buffers.length - 1; i >= 0; i--) {
			System.out.println(buffers[i].toString());
		}
		streamToWrite.println("Board has been updated!");
	}

	public Move onMove(Set<Move> moves, int myX, int myY) {
		streamToWrite.println("You are at (" + myX +", " + myY + "). Your move");
		printItemsWithIndex(moves);
		Move move = selectItemByIndex(moves);
		
		return move;
	}
	
	private <T> void printItemsWithIndex(Collection<T> items) {
		int index = 0;
		for (T item : items) {
			streamToWrite.println(index + ": " + item);
			index++;
		}
	}
	
	private <T> T selectItemByIndex(Collection<T> items) {
		T item= null;
		Enumeration<T> enumeration = Collections.enumeration(items);
		while(item == null) {
			streamToWrite.print("Select by index: ");
			int value = -1;
			try {
				value = Integer.parseInt(scanner.nextLine());
			} catch(NumberFormatException e) {
				streamToWrite.println("Bad input. please enter in a number");
				continue;
			}
			if (!inRange(value, items.size())) {
				streamToWrite.println("Number not in range");
				continue;
			}
			item = Collections.list(enumeration).get(value);
		}		
		
		return item;
	}

	public Creature onSelectCreature(List<Creature> arg0) {
		streamToWrite.println("Received select creature");
		printItemsWithIndex(arg0);
		return selectItemByIndex(arg0);
	}

	private boolean inRange(int selection, int size) {
		return selection >= 0 && selection < size;
	}

	public void onGameEndState(List<Player> arg0) {
		streamToWrite.println("game has ended!");
	}

	public void onGameLoadingState(List<Player> arg0) {
		streamToWrite.println("game is about to begin");
		streamToWrite.println("players in game:");
		
		for(Player player : arg0) {
			streamToWrite.println(player.getCommInfo().getName());
		}
	}

	public void onGameStartState(List<Player> arg0) {
		streamToWrite.println("game has started");
	}
}
